package com.company.project.wechat.miniProgram.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.company.project.sys.service.RedisService;
import com.company.project.wechat.commom.AesUtil;
import com.company.project.wechat.commom.HttpUtils;
import com.company.project.wechat.commom.WxPKCS7Encoder;
import com.company.project.wechat.miniProgram.service.LoginService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * @author ZYF
 * @date 2021/9/14 15:02
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    @Resource
    private RedisService redisService;

    @NacosValue(value = "${min.appId:1}", autoRefreshed = true)
    private String appId ;

    @NacosValue(value = "${mim.appSecret:1}", autoRefreshed = true)
    private String appSecret ;

    @Autowired
    HttpUtils httpUtils;

    /**
     *
     * @param jsCode 新的code
     * @param oldJsCode 旧的code
     * @param encryptedData 用户信息加密数据
     * @param iv 解密钥匙
     */
    @Override
    public HashMap<String,Object> login(String jsCode, String oldJsCode, String encryptedData, String iv){
        HashMap<String,Object> map =new HashMap<>();
        //先去查询redis是否缓存
        String code = redisService.get("js_code:"+oldJsCode);
        map.put("boole",true);
        if(StrUtil.isEmpty(code)){
            //此接口1分钟之内不能请求超过100次
            String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appId+"&secret="+appSecret+"&js_code="+jsCode+"&grant_type=authorization_code";
            log.info("登录接口地址：{}",url);
            String result = httpUtils.loadGetJson(url,null,"GET");
            log.info("登录接口微信返回信息：{}",result);
            JSONObject obj = JSONObject.parseObject(result);
            if(!obj.getString("code").equals("200")){
                log.error("小程序登录接口错误，返回状态码：{}",obj.getString("code"));
                map.put("boole",false);
            }else{
                code = result;
                String unionid = obj.getString("unionid");
                //若是从未关注过公众号以及未使用过小程序的，需要根据encryptedData、session_key、iv解密
                if(unionid==null) {
                    String sessionKey = obj.getString("session_key");
                    String decryptResult = decrypt(appId,encryptedData,sessionKey,iv);
                    JSONObject decryptObj = JSONObject.parseObject(decryptResult);
                    unionid = decryptObj.getString("unionId");
                    log.info("getUnionIdInfo unionid:"+unionid);
                }
                redisService.setAndExpire("js_code:"+code,code,60*5);
                map.put("boole",true);
            }
        }
        map.put("code",code);
        return map;
    }



    /**
     * 解密数据
     * @param microAppId 小程序id
     * @param encryptedData 机密数据
     * @param sessionKey 会话密钥
     * @param iv iv由数据接口返回
     * @return
     */
    public String decrypt(String microAppId, String encryptedData, String sessionKey, String iv){
        String result = "";
        try {
            AesUtil aes = new AesUtil();
            byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
            if(null != resultByte && resultByte.length > 0){
                result = new String(WxPKCS7Encoder.decode(resultByte));
                log.info("decrypt result:"+result);
                JSONObject obj = JSONObject.parseObject(result);
                String decryptAppid = obj.getJSONObject("watermark").getString("appid");
                if(!microAppId.equals(decryptAppid)){
                    result = "";
                }
            }
        } catch (Exception e) {
            result = "";
            e.printStackTrace();
        }
        return result;
    }
}
